#include "network.h"
#include "conn_tab.h"
static attack_t underAttack(rawPacket_t* packet, char *params){
	//XMAS packet
	if(packet->protocol == PROT_TCP){
		//params are tcp params
		tcpHeaderParams_t *tcpParams = (tcpHeaderParams_t *)params;
		if(tcpParams->syn && tcpParams->ack  && tcpParams->fin  && tcpParams->rst && tcpParams->urg  && tcpParams->ece  && tcpParams->cwr  && tcpParams->psh){
			return ATTACK_XMAS;
		}
	}
	return ATTACK_NONE;
}

static void makeRawPacket(struct sk_buff *skb, rawPacket_t *packet, tcpHeaderParams_t *params){
	struct iphdr *iph; 
	struct tcphdr *tcph;
	struct udphdr *udph;
		
	unsigned short sPort = 0, dPort = 0;	
	char protocol = 0;
	//char *pointer = 0;
	unsigned int size =0;
	//int i; 
	int linear_res =  (skb_linearize (skb) == 0); // linearize the packet
	iph = (struct iphdr *) skb_header_pointer(skb, 0, 0, NULL); // get IP header
	//iph = (struct iphdr *) skb->transport_header;
	//Version
	packet->version = iph->version;	
	//pointer += sizeof(struct iphdr);
	//Protocol and IPs
	packet->protocol = iph->protocol;
	packet->source_ip = ntohl(iph->saddr);
	packet->dest_ip = ntohl(iph->daddr);
	//Ports
	packet->data = 0;
	packet->data_length = 0;
	if(iph->protocol == PROT_TCP){ //TCP
		tcph = (struct tcphdr*)skb_header_pointer (skb,sizeof(struct iphdr), 0, NULL);		
		//tcph =  (struct tcphdr*)((char*)iph + (iph->ihl * 4));//(struct tcphdr*)skb_header_pointer (skb,sizeof(struct iphdr), 0, NULL);		
		params->syn = tcph->syn;
		params->ack = tcph->ack;
		params->fin = tcph->fin;
		params->rst = tcph->rst;
		params->urg = tcph->urg;
		params->ece = tcph->ece;
		params->cwr = tcph->cwr;
		params->psh = tcph->psh;
		sPort = ntohs(tcph->source);
		dPort = ntohs(tcph->dest);
		protocol = PROT_TCP;
		size = tcph->doff*4;	
		//packet->data_length = (unsigned int) ntohs(iph->tot_len) - ((iph->ihl << 2) + (tcph->doff << 2));	
	}else if(iph->protocol == PROT_UDP){ //UDP
		//udph = (struct udphdr*)skb_header_pointer (skb,sizeof(struct iphdr), 0, NULL);		
		//udph = (struct udphdr*)skb_header_pointer (skb,iph->ihl<<2, 0, NULL);		
		udph = (struct udphdr *)((__u32 *)iph + iph->ihl);
		sPort = ntohs(udph->source);
		dPort = ntohs(udph->dest);	
		protocol = PROT_UDP;
		size = sizeof(struct udphdr);		
	}else if(iph->protocol == PROT_ICMP){ //ICMP
		protocol = PROT_ICMP;	
		size = sizeof(struct icmphdr);			
	}
	packet->protocol = protocol;
	packet->source_port = sPort;
	packet->dest_port = dPort;	
	if(linear_res){		
		packet->data = (unsigned char *)(skb->data + size + (iph->ihl<<2));		
		//if(iph->protocol != PROT_TCP)
		packet->data_length = (unsigned char *)skb->tail - (unsigned char *)packet->data; 	
	}else{
		packet->data = NULL;
		packet->data_length = 0;
		printk("\n!!! not linearized !!!\n");
	}
    /*if(packet->data_length != 0 && packet->data != NULL && (protocol == PROT_TCP || protocol == PROT_UDP || protocol == PROT_ICMP)){
		printk("\n*********\n");
		printk("\n======== data length %d protocol %d ============\n",packet->data_length,packet->protocol);		
		for(i= 0;i<packet->data_length;++i){			
			printk("%c",packet->data[i]);
		}
		printk("\n======== end ============\n");
	}*/
	
}


//All ips are in computer endian
static __u32 applyMaskToIP(__u32 ip, __u8 mask){
	// zero out right bits
	__u32 result = ip;
	__u32 shiftBits = MAX_BITS_MASK - mask;
	int i;
	for(i=0;i<shiftBits;++i){
		result >>= 1;
	}
	for(i=0;i<shiftBits;++i){
		result <<= 1;
	}
	return result;
}
